package com.cardone.platform.authority.service;

import java.util.List;
import java.util.Map;
import java.util.UUID;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.Setter;

import org.apache.commons.lang3.ArrayUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.transaction.annotation.Transactional;

import com.cardone.common.dto.PaginationDto;
import com.cardone.common.utils.EntityUtils;
import com.cardone.persistent.CommonDtoAttributes;
import com.cardone.platform.authority.dao.RoleDao;
import com.cardone.platform.authority.dao.RolePermissionDao;
import com.cardone.platform.authority.dto.RoleDto;
import com.cardone.platform.authority.dto.RolePermissionDto;

/**
 * 角色服务
 * 
 * @author yaoht
 * 
 */
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class RoleDefaultService implements RoleService {
	/**
	 * 角色数据持久
	 */
	private RoleDao roleDao;

	/**
	 * 角色与许可数据持久
	 */
	private RolePermissionDao rolePermissionDao;

	@Override
	@Transactional
	@CacheEvict(value = RoleService.BEAN_ID, allEntries = true)
	public int deleteRoleByCode(@NonNull RoleDto deleteRole) {
		return this.roleDao.deleteByCode(deleteRole, new String[] {});
	}

	@Override
	@Transactional
	@CacheEvict(value = RoleService.BEAN_ID, allEntries = true)
	public int deleteRoleByIds(@NonNull RoleDto deleteRole) {
		return this.roleDao.deleteByIds(deleteRole);
	}

	@Override
	@Transactional
	@CacheEvict(value = RoleService.BEAN_ID, allEntries = true)
	public int deleteRolePermissionByCode(@NonNull RolePermissionDto deleteRolePermission) {
		return this.rolePermissionDao.deleteByCode(deleteRolePermission, new String[] {});
	}

	@Override
	@Transactional
	@CacheEvict(value = RoleService.BEAN_ID, allEntries = true)
	public int deleteRolePermissionByIds(@NonNull RolePermissionDto deleteRolePermission) {
		return this.rolePermissionDao.deleteByIds(deleteRolePermission);
	}

	@Override
	@Cacheable(value = RoleService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public List<RoleDto> findListRoleByCode(@NonNull RoleDto findListRole) {
		return this.roleDao.findListByCode(RoleDto.class, findListRole, new String[] {}, new String[] {});
	}

	@Override
	@Cacheable(value = RoleService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public List<RoleDto> findListRoleByName(@NonNull RoleDto findListRole) {
		return this.roleDao.findListByName(RoleDto.class, findListRole);
	}

	@Override
	@Cacheable(value = RoleService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public List<RolePermissionDto> findListRolePermissionByCode(@NonNull RolePermissionDto findListRolePermission) {
		return this.rolePermissionDao.findListByCode(RolePermissionDto.class, findListRolePermission, new String[] {}, new String[] {});
	}

	@Override
	@Cacheable(value = RoleService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public List<RolePermissionDto> findListRolePermissionByName(@NonNull RolePermissionDto findListRolePermission) {
		return this.rolePermissionDao.findListByName(RolePermissionDto.class, findListRolePermission);
	}

	@Override
	@Cacheable(value = RoleService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public RoleDto findRoleByCode(@NonNull RoleDto findRole) {
		return this.roleDao.findByCode(RoleDto.class, findRole, null, CommonDtoAttributes.id.name());
	}

	@Override
	@Cacheable(value = RoleService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public RoleDto findRoleById(@NonNull RoleDto findRole) {
		return this.roleDao.findByCode(RoleDto.class, findRole, null, CommonDtoAttributes.id.name());
	}

	@Override
	@Cacheable(value = RoleService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public RolePermissionDto findRolePermissionByCode(@NonNull RolePermissionDto findRolePermission) {
		return this.rolePermissionDao.findByCode(RolePermissionDto.class, findRolePermission, null, CommonDtoAttributes.id.name());
	}

	@Override
	@Cacheable(value = RoleService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public RolePermissionDto findRolePermissionById(@NonNull RolePermissionDto findRolePermission) {
		return this.rolePermissionDao.findByCode(RolePermissionDto.class, findRolePermission, null, CommonDtoAttributes.id.name());
	}

	@Override
	@Cacheable(value = RoleService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public PaginationDto<RoleDto> paginationRoleByCode(@NonNull RoleDto paginationRole) {
		return this.roleDao.paginationByCode(RoleDto.class, paginationRole);
	}

	@Override
	@Cacheable(value = RoleService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public PaginationDto<Map<String, Object>> paginationRoleByName(@NonNull RoleDto paginationRole) {
		return this.roleDao.paginationByName(paginationRole);
	}

	@Override
	@Cacheable(value = RoleService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public PaginationDto<RolePermissionDto> paginationRolePermissionByCode(@NonNull RolePermissionDto paginationRolePermission) {
		return this.rolePermissionDao.paginationByCode(RolePermissionDto.class, paginationRolePermission);
	}

	@Override
	@Cacheable(value = RoleService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public PaginationDto<Map<String, Object>> paginationRolePermissionByName(@NonNull RolePermissionDto paginationRolePermission) {
		return this.rolePermissionDao.paginationByName(paginationRolePermission);
	}

	@Override
	@Cacheable(value = RoleService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public Integer readRoleByCodeNqId(@NonNull RoleDto readRole) {
		return this.roleDao.readByCodeNqId(Integer.class, readRole);
	}

	@Override
	@Cacheable(value = RoleService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public Integer readRoleByName(@NonNull RoleDto readRole) {
		return this.roleDao.readByName(Integer.class, null, readRole);
	}

	@Override
	@Cacheable(value = RoleService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public Integer readRolePermissionByCodeNqId(@NonNull RolePermissionDto readRolePermission) {
		return this.rolePermissionDao.readByCodeNqId(Integer.class, readRolePermission);
	}

	@Override
	@Cacheable(value = RoleService.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public Integer readRolePermissionByName(@NonNull RolePermissionDto readRolePermission) {
		return this.rolePermissionDao.readByName(Integer.class, null, readRolePermission);
	}

	@Override
	@CacheEvict(value = RoleService.BEAN_ID, allEntries = true)
	public void reload() {
		this.roleDao.reload();

		this.rolePermissionDao.reload();
	}

	@Override
	@Transactional
	@CacheEvict(value = RoleService.BEAN_ID, allEntries = true)
	public RoleDto saveRoleByIdOrCode(@NonNull RoleDto saveRole) {
		final String[] whereAndEqProperties = EntityUtils.getWhereProperties(saveRole, CommonDtoAttributes.code.name());

		final RoleDto oldRole = this.roleDao.findByCode(RoleDto.class, saveRole, null, whereAndEqProperties);

		if (oldRole == null) {
			saveRole.setId(UUID.randomUUID().toString());

			this.roleDao.insertByCode(saveRole);

			final String[] notNullIdProperties = EntityUtils.getNotNullIdProperties(saveRole);

			return this.roleDao.findByCode(RoleDto.class, saveRole, null, notNullIdProperties);
		}

		final String[] useProperties = EntityUtils.addNotNullTimeSegmentProperties(new String[] { CommonDtoAttributes.parentId.name(),
		        CommonDtoAttributes.typeId.name(), CommonDtoAttributes.code.name(), CommonDtoAttributes.name.name(),
		        CommonDtoAttributes.orderCode.name(), CommonDtoAttributes.value.name(), CommonDtoAttributes.remark.name() }, saveRole);

		final String[] updateProperties = com.cardone.common.utils.BeanUtils.diffProperties(saveRole, oldRole, useProperties);

		if (ArrayUtils.isEmpty(updateProperties)) {
			return oldRole;
		}

		final String[] notNullIdProperties = EntityUtils.getNotNullIdProperties(oldRole);

		com.cardone.common.utils.BeanUtils.copyProperties(oldRole, saveRole, notNullIdProperties);

		this.roleDao.updateByCode(saveRole, updateProperties, notNullIdProperties);

		return this.roleDao.findByCode(RoleDto.class, oldRole, null, notNullIdProperties);
	}

	@Override
	@Transactional
	@CacheEvict(value = RoleService.BEAN_ID, allEntries = true)
	public RoleDto saveRoleByName(@NonNull RoleDto saveRole) {
		final String[] whereAndEqProperties = EntityUtils.getWhereProperties(saveRole, CommonDtoAttributes.code.name());

		final RoleDto oldRole = this.roleDao.findByCode(RoleDto.class, saveRole, null, whereAndEqProperties);

		if (oldRole == null) {
			saveRole.setId(UUID.randomUUID().toString());

			this.roleDao.insertByCode(saveRole);

			final String[] notNullIdProperties = EntityUtils.getNotNullIdProperties(saveRole);

			return this.roleDao.findByCode(RoleDto.class, saveRole, null, notNullIdProperties);
		}

		final String[] useProperties = EntityUtils.addNotNullTimeSegmentProperties(new String[] { CommonDtoAttributes.parentId.name(),
		        CommonDtoAttributes.typeId.name(), CommonDtoAttributes.code.name(), CommonDtoAttributes.name.name(),
		        CommonDtoAttributes.orderCode.name(), CommonDtoAttributes.value.name(), CommonDtoAttributes.remark.name() }, saveRole);

		final String[] updateProperties = com.cardone.common.utils.BeanUtils.diffProperties(saveRole, oldRole, useProperties);

		if (ArrayUtils.isEmpty(updateProperties)) {
			return oldRole;
		}

		final String[] notNullIdProperties = EntityUtils.getNotNullIdProperties(oldRole);

		com.cardone.common.utils.BeanUtils.copyProperties(oldRole, saveRole, notNullIdProperties);

		this.roleDao.updateByCode(saveRole, updateProperties, notNullIdProperties);

		return this.roleDao.findByCode(RoleDto.class, oldRole, null, notNullIdProperties);
	}

	@Override
	@Transactional
	@CacheEvict(value = RoleService.BEAN_ID, allEntries = true)
	public RolePermissionDto saveRolePermissionByIdOrCode(@NonNull RolePermissionDto saveRolePermission) {
		final String[] whereAndEqProperties = EntityUtils.getWhereProperties(saveRolePermission, CommonDtoAttributes.code.name());

		final RolePermissionDto oldRolePermission = this.rolePermissionDao.findByCode(RolePermissionDto.class, saveRolePermission,
		        null, whereAndEqProperties);

		if (oldRolePermission == null) {
			saveRolePermission.setId(UUID.randomUUID().toString());

			this.rolePermissionDao.insertByCode(saveRolePermission);

			final String[] notNullIdProperties = EntityUtils.getNotNullIdProperties(saveRolePermission);

			return this.rolePermissionDao.findByCode(RolePermissionDto.class, saveRolePermission, null, notNullIdProperties);
		}

		final String[] useProperties = EntityUtils.addNotNullTimeSegmentProperties(new String[] { CommonDtoAttributes.parentId.name(),
		        CommonDtoAttributes.typeId.name(), CommonDtoAttributes.code.name(), CommonDtoAttributes.name.name(),
		        CommonDtoAttributes.orderCode.name(), CommonDtoAttributes.value.name(), CommonDtoAttributes.remark.name() },
		        saveRolePermission);

		final String[] updateProperties = com.cardone.common.utils.BeanUtils.diffProperties(saveRolePermission, oldRolePermission,
		        useProperties);

		if (ArrayUtils.isEmpty(updateProperties)) {
			return oldRolePermission;
		}

		final String[] notNullIdProperties = EntityUtils.getNotNullIdProperties(oldRolePermission);

		com.cardone.common.utils.BeanUtils.copyProperties(oldRolePermission, saveRolePermission, notNullIdProperties);

		this.rolePermissionDao.updateByCode(saveRolePermission, updateProperties, notNullIdProperties);

		return this.rolePermissionDao.findByCode(RolePermissionDto.class, oldRolePermission, null, notNullIdProperties);
	}

	@Override
	@Transactional
	@CacheEvict(value = RoleService.BEAN_ID, allEntries = true)
	public RolePermissionDto saveRolePermissionByName(@NonNull RolePermissionDto saveRolePermission) {
		final String[] whereAndEqProperties = EntityUtils.getWhereProperties(saveRolePermission, CommonDtoAttributes.code.name());

		final RolePermissionDto oldRolePermission = this.rolePermissionDao.findByCode(RolePermissionDto.class, saveRolePermission,
		        null, whereAndEqProperties);

		if (oldRolePermission == null) {
			saveRolePermission.setId(UUID.randomUUID().toString());

			this.rolePermissionDao.insertByCode(saveRolePermission);

			final String[] notNullIdProperties = EntityUtils.getNotNullIdProperties(saveRolePermission);

			return this.rolePermissionDao.findByCode(RolePermissionDto.class, saveRolePermission, null, notNullIdProperties);
		}

		final String[] useProperties = EntityUtils.addNotNullTimeSegmentProperties(new String[] { CommonDtoAttributes.parentId.name(),
		        CommonDtoAttributes.typeId.name(), CommonDtoAttributes.code.name(), CommonDtoAttributes.name.name(),
		        CommonDtoAttributes.orderCode.name(), CommonDtoAttributes.value.name(), CommonDtoAttributes.remark.name() },
		        saveRolePermission);

		final String[] updateProperties = com.cardone.common.utils.BeanUtils.diffProperties(saveRolePermission, oldRolePermission,
		        useProperties);

		if (ArrayUtils.isEmpty(updateProperties)) {
			return oldRolePermission;
		}

		final String[] notNullIdProperties = EntityUtils.getNotNullIdProperties(oldRolePermission);

		com.cardone.common.utils.BeanUtils.copyProperties(oldRolePermission, saveRolePermission, notNullIdProperties);

		this.rolePermissionDao.updateByCode(saveRolePermission, updateProperties, notNullIdProperties);

		return this.rolePermissionDao.findByCode(RolePermissionDto.class, oldRolePermission, null, notNullIdProperties);
	}

	@Override
	@Transactional
	@CacheEvict(value = RoleService.BEAN_ID, allEntries = true)
	public int updateRoleByCode(@NonNull RoleDto updateRole) {
		return this.roleDao.updateByCode(updateRole, new String[] {}, new String[] {});
	}

	@Override
	@Transactional
	@CacheEvict(value = RoleService.BEAN_ID, allEntries = true)
	public int updateRoleByIds(@NonNull RoleDto updateRole) {
		return this.roleDao.updateByIds(updateRole);
	}

	@Override
	@Transactional
	@CacheEvict(value = RoleService.BEAN_ID, allEntries = true)
	public int updateRolePermissionByCode(@NonNull RolePermissionDto updateRolePermission) {
		return this.rolePermissionDao.updateByCode(updateRolePermission, new String[] {}, new String[] {});
	}

	@Override
	@Transactional
	@CacheEvict(value = RoleService.BEAN_ID, allEntries = true)
	public int updateRolePermissionByIds(@NonNull RolePermissionDto updateRolePermission) {
		return this.rolePermissionDao.updateByIds(updateRolePermission);
	}
}